import java.math.BigInteger;
import java.net.InetAddress;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.DHParameterSpec;
import javax.crypto.spec.SecretKeySpec;



class Client
     {
    	 InetAddress IPAddress;
    	 int port;
    	 String name;
    	 long random1;
    	 long random2;
    	 KeyPair DHKeyPair;
    	 byte[] pubKey;
    	 byte[] cliSerKey;
    	 ClientStatus status;
    	 Cipher publicEncodeCipher;
    	 Cipher publicDecodeCipher;
    	 
    	 Cipher AESEncodeCipher;
    	 Cipher AESDecodeCipher;
    	 
    	 static enum ClientStatus {
  		   disConnected,WaitingSendRequestAck, WaitingSessionStart, WaitingSessionStartAck, WaitLoginChallenge, WaitLoginResponse, WaitLoginSessionStart, Connnected
  		 };
    	 
    	 Client(InetAddress ip, int p)
    	 {
    		 IPAddress = ip;
    		 port = p;
    		 status = ClientStatus.WaitLoginChallenge;
    	 }
    	 
    	 Client(String n)
    	 {
    		 name = n;
    		 status = ClientStatus.disConnected;
    	 }
    	 
    	 public void setPublicCipher(byte[] publicKey)
    	 {
    		PublicKey publick;
			try
			{
				publick = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(publicKey));
				publicEncodeCipher = Cipher.getInstance("RSA/NONE/PKCS1Padding");
	    		publicEncodeCipher.init(Cipher.ENCRYPT_MODE, publick);
					
	    		publicDecodeCipher = Cipher.getInstance("RSA/NONE/PKCS1Padding");
	    		publicDecodeCipher.init(Cipher.DECRYPT_MODE, publick);
			} 
			catch (Exception e)
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
    		
    	 }
    	 
    	 public void setDHKeyPair(BigInteger p512, BigInteger g512)
    	 {
    		 try
 	 		{   		   	 
 		     DHParameterSpec servParamSpec = new DHParameterSpec(p512, g512);  	 
 		     KeyPairGenerator servKPG = KeyPairGenerator.getInstance("DH");
 	         servKPG.initialize(servParamSpec);
 	         DHKeyPair = servKPG.generateKeyPair();
 	 		}
 		    catch(Exception e)
 		    {
 		    	// TODO Auto-generated catch block
 				e.printStackTrace();
 		    }
    	 }
    	  	
    	 public void initAESCipher(byte[] key)
    	 {
    		 try
    		 {
    		   AESEncodeCipher = Cipher.getInstance("AES"); 		   
    		   SecretKey k = new SecretKeySpec(key, 0, 16, "AES");
    		   AESEncodeCipher.init(Cipher.ENCRYPT_MODE, k);
    		   
    		   AESDecodeCipher = Cipher.getInstance("AES"); 		   
    		   k = new SecretKeySpec(key, 0, 16, "AES");
    		   AESDecodeCipher.init(Cipher.DECRYPT_MODE, k);
    		 }
    		 catch(Exception e)
    		 {
    			 e.printStackTrace();
    		 }
    	 }
     }